package philbot;

import java.util.LinkedList;
import java.util.List;
/**
 * This class represents a single game of PhutBall
 * Mutable.  Should only be "played" once per instance
 * @author philip
 *
 */
public class SingleGame {
	private BotHolder goesFirst;
	private BotHolder goesSecond;
	private AbstractPosition startingPosition; 
	private int maximumNumberOfTurns;
	private int winner;
	private int numberOfTurns;
	private double at1,at2,atTotal;
	private List<AbstractPosition> positionsInGame;
	/**
	 * Constructor of a game
	 * @param goesFirst the bot that gets to go first
	 * @param goesSecond the bot that goes second
	 * @param startingPosition the inital position
	 * @param maximumNumerOfTurns a number of turns before the game automatically ends in a tie
	 */
	public SingleGame(BotHolder goesFirst, BotHolder goesSecond, AbstractPosition startingPosition, int maximumNumerOfTurns){
		this.goesFirst = goesFirst;
		this.goesSecond = goesSecond;
		this.startingPosition = startingPosition;
		this.maximumNumberOfTurns = maximumNumerOfTurns;
		this.positionsInGame = new LinkedList<AbstractPosition>();
	}
	
	/**
	 * Play the game, updating all data in the class
	 * @param loud a parameter to determine if text should be written to the screen 
	 */
	public void play(boolean loud){
		AbstractPosition current = startingPosition;
		boolean turn = true;
		BotHolder player;
		boolean done = false;
		List<Long> times1 = new LinkedList<Long>();
		List<Long> times2 = new LinkedList<Long>();
		for(numberOfTurns = 1; numberOfTurns < maximumNumberOfTurns; numberOfTurns++){
			if(loud){
				System.out.println("On the " + numberOfTurns + " turn");
				System.out.println(current);
			}
			positionsInGame.add(current);
			if(current.isVictory()){
				done = true;
				break;
			}
			player = turn ? goesFirst : goesSecond;
			long start = System.nanoTime();
			try{
				current = player.play(current);
			}finally{
				long end = System.nanoTime();
				List<Long> list = turn ? times1 : times2;
				list.add(end-start);
			}
			turn = !turn;
		}
		if(done){
			winner = current.whoVictory();
		}else{
			winner = 0;
		}
		at1 = average(times1);
		at2 = average(times2);
		times1.addAll(times2);
		atTotal = average(times1);
	}
	private double average(List<Long> l){
		if(l.size() == 0){
			return 0;
		}
		double sum = 0;
		for(Long i: l){
			sum+=i;
		}
		return sum/((double)l.size());
	}
	/**
	 * @see philbot.AbstractPosition#whoVictory()
	 * @return the game winner
	 */
	public int getWinner(){
		return winner;
	}
	/**
	 * 
	 * @return The average time per turn used by player 1 in nano seconds
	 */
	public double getAverageTimePlayer1(){
		return at1;
	}
	/**
	 * 
	 * @return The average time per turn used by player 2 in nano seconds
	 */
	public double getAverageTimePlayer2(){
		return at2;
	}
	/**
	 * 
	 * @return The average time per turn used by both players in nano seconds
	 */
	public double getAverageTimeBothPlayers(){
		return atTotal;
	}
	/**
	 * 
	 * @return the positions played in the game (in order)
	 */
	public List<AbstractPosition> getPositions(){
		return positionsInGame;
	}

}
